import GomokuCommon
import UIKit

// 主视图控制者
class ViewController: UIViewController, InputBoxCallback, RivalWindowCallback {
    private var mGame: Game!                        // 游戏
    @IBOutlet weak var mLabelRivalName: UILabel!    // "当前对手"标签
    private var mMenuItemDefeat: UIAction!          // "认输"菜单项
    private var mMenuItemFindUsers: UIAction!       // "寻找其它用户"菜单项
    private var mMenuItemRestart: UIAction!         // "再来一局"菜单项
    private var mRivalWindow: RivalWindow!          // 对手列表窗口
    
    /**
     * 改变界面状态。
     * @param attribute 菜单属性
     * @return 菜单
     */
    private func changeState(_ attributes: [UIAction.Attributes]) -> UIMenu {
        mMenuItemFindUsers.attributes = attributes[0]
        mMenuItemDefeat.attributes = attributes[1]
        mMenuItemRestart.attributes = attributes[2]
        return UIMenu(title: "", subtitle: nil, image: nil, identifier: nil, options: [], children: [mMenuItemFindUsers, mMenuItemDefeat, mMenuItemRestart])
    }

    /**
     * 关闭游戏。
     */
    public func closeGame() {
        mGame.close()
    }

    /**
     * 创建菜单。
     * @return 菜单
     */
    private func createMenu() -> UIMenu {
        // "寻找其它用户"菜单项
        var title = NSLocalizedString("IDS_FIND_USERS", tableName: "Main", comment: "")
        mMenuItemFindUsers = UIAction(title: title) {
            _ in
            self.onMenuItemFindUsersClicked()
        }
        
        // "认输"菜单项
        title = NSLocalizedString("IDS_DEFEAT", tableName: "Main", comment: "")
        mMenuItemDefeat = UIAction(title: title, subtitle: nil, image: nil, identifier: nil, discoverabilityTitle: nil, attributes: [.disabled]) {
            _ in
            self.onMenuItemDefeatClicked()
        }
        
        // "再来一局"菜单项
        title = NSLocalizedString("IDS_RESTART", tableName: "Main", comment: "")
        mMenuItemRestart = UIAction(title: title, subtitle: nil, image: nil, identifier: nil, discoverabilityTitle: nil, attributes: [.disabled]) {
            _ in
            self.onMenuItemRestartClicked()
        }
        
        return UIMenu(title: "", subtitle: nil, image: nil, identifier: nil, options: [], children: [mMenuItemFindUsers, mMenuItemDefeat, mMenuItemRestart])
    }

    /**
     * 网络连接完成事件的响应方法。
     * @param notification  通知
     */
    @objc private func onConnected(notification: Notification) {
        let result = notification.object as! Bool
        if result {
            // 登录
            let tipText = NSLocalizedString("IDS_INPUT_USERNAME", tableName: "Main", comment: "")
            InputBox(self, tipText: tipText, viewController: self).show()
        } else {
            // 弹出提示
            let text = NSLocalizedString("IDS_NETWORK_ERROR", tableName: "Main", comment: "")
            let titleOK = NSLocalizedString("IDS_OK", tableName: "Main", comment: "")
            let alertDialog = UIAlertController(title: " ", message: text, preferredStyle: .alert)
            alertDialog.addAction(UIAlertAction(title: titleOK, style: .default, handler: {
                _ in
                exit(0)
            }))
            super.present(alertDialog, animated: true)
        }
    }
    
    /**
     * 单击游戏区域事件的响应方法。
     * @param recognizer    事件相关信息
     */
    @objc private func onGameBoardClicked(recognizer: UITapGestureRecognizer) {
        let position = recognizer.location(in: recognizer.view)
        mGame.onGameBoardClicked(Int(position.x), y: Int(position.y))
    }
    
    /**
     * 游戏结束事件的响应方法。
     * @param reason    结束原因
     */
    @objc private func onGameOver(notification: Notification) {
        // 设置菜单项
        navigationItem.rightBarButtonItem?.menu = self.changeState([[], [.disabled], []])

        // 显示提示信息
        var message: String
        let reason = notification.object as! GameOverReason
        switch reason {
            case .LOST:
                message = NSLocalizedString("IDS_LOST", tableName: "Main", comment: "")
            case .RIVAL_ADMIT:
                message = NSLocalizedString("IDS_RIVAL_ADMIT", tableName: "Main", comment: "")
            case .SELF_ADMIT:
                message = NSLocalizedString("IDS_SELF_ADMIT", tableName: "Main", comment: "")
            case .WON:
                message = NSLocalizedString("IDS_WON", tableName: "Main", comment: "")
        }
        let alertDialog = UIAlertController(title: " ", message: message, preferredStyle: .alert)
        let titleOK = NSLocalizedString("IDS_OK", tableName: "Main", comment: "")
        alertDialog.addAction(UIAlertAction(title: titleOK, style: .default))
        super.present(alertDialog, animated: true)
    }
    
    /**
     * 游戏开始事件的响应方法。
     * @param notification  通知
     */
    @objc private func onGameStart(notification: Notification) {
        // 隐藏对手列表窗口
        if mRivalWindow != nil {
            mRivalWindow.hide()
        }

        // 设置菜单项
        navigationItem.rightBarButtonItem?.menu = self.changeState([[.disabled], [], [.disabled]])

        // 显示对手的名字
        let rivalName = notification.object as! String
        mLabelRivalName.text = NSLocalizedString("IDS_CURRENT_RIVAL", tableName: "Main", comment: "") + rivalName
    }
    
    /**
     * 得到寻找用户结果事件的响应方法。
     * @param notification  通知
     */
    @objc private func onGetFindUsersResult(notification: Notification) {
        let result = notification.object as! FindUsersResult
        if result.mUsernameList!.count > 0 {
            mRivalWindow.setUsernameList(result.mUsernameList)
            mRivalWindow.show()
        }
    }
    
    /**
     * 得到挑战请求事件的响应方法。
     * @param notification  通知
     */
    @objc private func onGetInviteRequest(notification: Notification) {
        // 弹出选择提示窗口
        let rivalName = notification.object as! String
        let titleNo = NSLocalizedString("IDS_NO", tableName: "Main", comment: "")
        let titleYes = NSLocalizedString("IDS_YES", tableName: "Main", comment: "")
        let question = rivalName + NSLocalizedString("IDS_INVITE", tableName: "Main", comment: "")
        let alertDialog = UIAlertController(title: " ", message: question, preferredStyle: .alert)
        alertDialog.addAction(UIAlertAction(title: titleNo, style: .cancel, handler: {
            // 用户单击了"否"
            [self] _ in
            mGame.acceptInvite(rivalName, accept: false)
        }))
        alertDialog.addAction(UIAlertAction(title: titleYes, style: .default, handler: {
            // 用户单击了"是"
            [self] _ in
            mGame.acceptInvite(rivalName, accept: true)
        }))
        super.present(alertDialog, animated: true)
    }
    
    /**
     * 得到挑战结果事件的响应方法。
     * @param notification  通知
     */
    @objc private func onGetInviteResult(notification: Notification) {
        // 弹出提示框
        let result = notification.object as! InviteResult
        var information = result.mRivalName
        if result.mAccept {
            information += NSLocalizedString("IDS_ACCEPT", tableName: "Main", comment: "")
        } else {
            information += NSLocalizedString("IDS_REFUSE", tableName: "Main", comment: "")
        }
        let titleOK = NSLocalizedString("IDS_OK", tableName: "Main", comment: "")
        let messageBox = UIAlertController(title: nil, message: information, preferredStyle: .alert)
        messageBox.addAction(UIAlertAction(title: titleOK, style: .default))
        super.present(messageBox, animated: true)
    }
    
    /**
     * 得到登录结果事件的响应方法。
     * @param notification  通知
     */
    @objc private func onGetLogonResult(notification: Notification) {
        let result = notification.object as! Bool
        if result {
            let text = NSLocalizedString("IDS_LOGON_SUCCEEDED", tableName: "Main", comment: "")
            Toast.makeText(view, text: text, duration: Toast.LENGTH_SHORT).show()
        } else {
            let text = NSLocalizedString("IDS_LOGON_FAILED", tableName: "Main", comment: "")
            Toast.makeText(view, text: text, duration: Toast.LENGTH_LONG).show()
            let tipText = NSLocalizedString("IDS_INPUT_USERNAME", tableName: "Main", comment: "")
            InputBox(self, tipText: tipText, viewController: self).show()
        }
    }

    /**
    * 获取对手的名字事件的响应方法。
     * @param notification  通知
    */
    @objc private func OnGetRivalName(notification: Notification) {
        let rivalName = notification.object as! String
        mGame.invite(rivalName)
    }
    
    /**
     * 输入窗口的"取消"按钮的单击响应方法。
     */
    internal func onInputBoxCancel() {
        mGame.close()
        exit(0)
    }
    
    /**
     * 输入窗口的"确定"按钮的单击响应方法。
     * @param intValue  用户输入的数值
     */
    internal func onInputBoxOK(_ intValue: Int) {
    }

    /**
     * 输入窗口的"确定"按钮的单击响应方法。
     * @param stringValue   用户输入的文字
     */
    internal func onInputBoxOK(_ stringValue: String) {
        mGame.logon(stringValue)
    }

    /**
     * "认输"菜单项的单击响应方法。
     */
    private func onMenuItemDefeatClicked() {
        mGame.defeat()
    }
    
    /**
     * "寻找其它用户"菜单项的单击响应方法。
     */
    private func onMenuItemFindUsersClicked() {
        mGame.findUsers()
    }

    /**
     * "再来一局"菜单项的单击响应方法。
     */
    private func onMenuItemRestartClicked() {
        mGame.restart()
    }
    
    /**
     * 对手退出游戏事件的响应方法。
     * @param notification  通知
     */
    @objc private func onRivalQuitGame(notification: Notification) {
        // 设置菜单项
        navigationItem.rightBarButtonItem?.menu = self.changeState([[], [.disabled], [.disabled]])

        // 设置状态栏
        mLabelRivalName.text = NSLocalizedString("IDS_CURRENT_RIVAL", tableName: "Main", comment: "")

        // 显示提示信息
        let escape = notification.userInfo![Const.KEY_STATUS] as! Bool
        var text = notification.userInfo![Const.KEY_USERNAME] as! String
        if escape {
            text += NSLocalizedString("IDS_RIVAL_ESCAPE", tableName: "Main", comment: "")
            let titleOK = NSLocalizedString("IDS_OK", tableName: "Main", comment: "")
            let alertDialog = UIAlertController(title: " ", message: text, preferredStyle: .alert)
            alertDialog.addAction(UIAlertAction(title: titleOK, style: .default))
            super.present(alertDialog, animated: true)
        } else {
            text += NSLocalizedString("IDS_RIVAL_QUIT", tableName: "Main", comment: "")
            Toast.makeText(view, text: text, duration: Toast.LENGTH_SHORT).show()
        }
    }
    
    /**
     * 对手列表窗口的"确定"按钮的单击响应方法。
     * @param selectedName  用户选择的用户名
     */
    internal func onRivalWindowOK(_ selectedName: String) {
        mGame.invite(selectedName)
    }

    /**
     * 视图加载事件的响应方法。
     */
    internal override func viewDidLoad() {
        super.viewDidLoad()
        
        // 将自身保存到应用代理中
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        appDelegate.viewController = self
        
        // 将本页面设置为首页
        let window = UIApplication.shared.delegate?.window!
        window!.rootViewController = UINavigationController(rootViewController: self)
        
        // 添加菜单按钮(...按钮)
        navigationItem.rightBarButtonItem = UIBarButtonItem(title: "...", style: .done, target: self, action: nil)
        
        // 创建菜单
        navigationItem.rightBarButtonItem?.menu = self.createMenu()
        
        // 设置主视图背景色
        view.backgroundColor = Const.COLOR
        
        // 计算控件尺寸和位置
        let screenWidth = Int(UIScreen.main.bounds.width)   // 屏幕宽度
        let screenHeight = Int(UIScreen.main.bounds.height) // 屏幕高度
        let gridCount = Const.GAME_BOARD_POINT_COUNT_H + 1  // 棋盘格数(棋盘左右边缘到屏幕边缘的空白区域各算1格)

        Const.GRID_SIZE = screenWidth / gridCount   // 格的尺寸

        let statusBarHeight = Int((UIApplication.shared.windows.first!.windowScene!.statusBarManager?.statusBarFrame.height)!)  // 状态栏高度
        
        let lblWidth = screenWidth                                          // 标签宽度
        let lblHeight = Int(Float(screenHeight) * Const.SCALE_LABEL_HEIGHT) // 标签高度

        let gameBoardSize = Const.GRID_SIZE * gridCount      // 游戏区域尺寸
        let gameBoardX = (screenWidth - gameBoardSize) / 2  // 游戏区域左上角 X 坐标
        let gameBoardY = (screenHeight + statusBarHeight - gameBoardSize - lblHeight) / 2   // 游戏区域左上角 Y 坐标
        
        let lblX = 0                            // "当前对手"标签左上角 X 坐标
        let lblY = gameBoardY + gameBoardSize   // "当前对手"标签左上角 Y 坐标
        mLabelRivalName.frame = CGRect(x: lblX, y: lblY, width: lblWidth, height: lblHeight)
        
        // 创建对手列表窗口
        mRivalWindow = RivalWindow(self, parentController: self)
        
        // 创建游戏区域
        let gameBoard = GameBoard(frame: CGRect(x: gameBoardX, y: gameBoardY, width: gameBoardSize, height: gameBoardSize))
        view.addSubview(gameBoard)
        let recognizer = UITapGestureRecognizer(target: self, action:#selector(onGameBoardClicked))
        gameBoard.addGestureRecognizer(recognizer)
        
        // 创建游戏
        mGame = Game(gameBoard.drawer, gameBoard: gameBoard)
        
        // 订阅事件
        let notificationCenter = NotificationCenter.default
        notificationCenter.addObserver(self, selector: #selector(onConnected), name: Const.UM_CONNECTED, object: nil)
        notificationCenter.addObserver(self, selector: #selector(onGameOver), name: Const.UM_GAME_OVER, object: nil)
        notificationCenter.addObserver(self, selector: #selector(onGameStart), name: Const.UM_GAME_START, object: nil)
        notificationCenter.addObserver(self, selector: #selector(onGetFindUsersResult), name: Const.UM_GET_FIND_USERS_RESULT, object: nil)
        notificationCenter.addObserver(self, selector: #selector(onGetInviteRequest), name: Const.UM_GET_INVITE_REQUEST, object: nil)
        notificationCenter.addObserver(self, selector: #selector(onGetInviteResult), name: Const.UM_GET_INVITE_RESULT, object: nil)
        notificationCenter.addObserver(self, selector: #selector(onGetLogonResult), name: Const.UM_GET_LOGON_RESULT, object: nil)
        notificationCenter.addObserver(self, selector: #selector(onRivalQuitGame), name: Const.UM_RIVAL_QUIT_GAME, object: nil)
    }
}
